﻿using UnityEngine;
using System.Collections;
//引入库
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System;
using System.Collections.Generic;
using Google.Protobuf;
using UnityEngine.SceneManagement;

public class TcpClient : MonoBehaviour
{
    //string editString = "hello wolrd"; //编辑框文字

    Socket serverSocket; //服务器端socket
    IPAddress ip; //主机ip
    IPEndPoint ipEnd;
    string recvStr; //接收的字符串
    string sendStr; //发送的字符串
    byte[] recvData = new byte[1024]; //接收的数据，必须为字节
    byte[] sendData = new byte[1024]; //发送的数据，必须为字节
    int recvLen; //接收的数据长度
    Thread connectThread; //连接线程

    static readonly object locker = new object();
    List<byte[]> recvQueue = new List<byte[]>();

    public static TcpClient Instance
    {
        get; private set;
    }

    //void Awake()
    //{
    //    //if (Instance != null)
    //    //{
    //    //    Destroy(gameObject);
    //    //    return;
    //    //}
    //    if (Instance == null)
    //    {
    //        Instance = this;
    //        DontDestroyOnLoad(gameObject);

    //        Init();
    //    }

    //}



    //初始化
    void InitSocket()
    {
        //定义服务器的IP和端口，端口与服务器对应
        ip = IPAddress.Parse("127.0.0.1"); //可以是局域网或互联网ip，此处是本机
        ipEnd = new IPEndPoint(ip, 3563);


        //开启一个线程连接，必须的，否则主线程卡死
        connectThread = new Thread(new ThreadStart(SocketReceive));
        connectThread.Start();
    }

    void SocketConnet()
    {
        if (serverSocket != null)
            serverSocket.Close();
        //定义套接字类型,必须在子线程中定义
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        print("ready to connect");
        //连接
        serverSocket.Connect(ipEnd);

        //输出初次连接收到的字符串
        //recvLen = serverSocket.Receive(recvData);
        //recvStr = Encoding.ASCII.GetString(recvData, 0, recvLen);
        //print(recvStr);
    }

    public void SocketSend(byte[] sendData)
    {
        ////清空发送缓存
        //sendData = new byte[1024];
        ////数据类型转换
        //sendData = Encoding.ASCII.GetBytes(sendStr);

        byte[] head = MsgMgr.Instance.GetBytes((ushort)sendData.Length);


        byte[] sendBuffer = new byte[sendData.Length + 2];
        head.CopyTo(sendBuffer, 0);
        sendData.CopyTo(sendBuffer, 2);

        //发送
        serverSocket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None);
    }

    public void SocketSend<T>(byte[] sendData)
    {

        int id = MsgMgr.Instance.GetId<T>();
        byte[] msgId = MsgMgr.Instance.GetBytes((ushort)id);

        byte[] sendBytesWithId = new byte[sendData.Length + msgId.Length];
        msgId.CopyTo(sendBytesWithId, 0);
        sendData.CopyTo(sendBytesWithId, msgId.Length);

        ////清空发送缓存
        //sendData = new byte[1024];
        ////数据类型转换
        //sendData = Encoding.ASCII.GetBytes(sendStr);

        byte[] head = MsgMgr.Instance.GetBytes((ushort)sendBytesWithId.Length);


        byte[] sendBuffer = new byte[sendBytesWithId.Length + 2];
        head.CopyTo(sendBuffer, 0);
        sendBytesWithId.CopyTo(sendBuffer, 2);

        //发送
        serverSocket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None);
    }

    public void SocketSend<T>(IMessage message)
    {
        byte[] sendData = message.ToByteArray();

        int id = MsgMgr.Instance.GetId<T>();
        byte[] msgId = MsgMgr.Instance.GetBytes((ushort)id);

        byte[] sendBytesWithId = new byte[sendData.Length + msgId.Length];
        msgId.CopyTo(sendBytesWithId, 0);
        sendData.CopyTo(sendBytesWithId, msgId.Length);

        ////清空发送缓存
        //sendData = new byte[1024];
        ////数据类型转换
        //sendData = Encoding.ASCII.GetBytes(sendStr);

        byte[] head = MsgMgr.Instance.GetBytes((ushort)sendBytesWithId.Length);


        byte[] sendBuffer = new byte[sendBytesWithId.Length + 2];
        head.CopyTo(sendBuffer, 0);
        sendBytesWithId.CopyTo(sendBuffer, 2);

        //发送
        serverSocket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None);
    }

    void SocketReceive()
    {
        SocketConnet();
        //不断接收服务器发来的数据
        while (true)
        {
            recvData = new byte[1024];
            recvLen = serverSocket.Receive(recvData);
            if (recvLen == 0)
            {
                SocketConnet();
                continue;
            }
            byte[] dest = new byte[recvLen];
            Array.Copy(recvData, dest, recvLen);

            AddRecvBuffer(dest);
            //recvStr = Encoding.ASCII.GetString(recvData, 0, recvLen);
            //print(recvStr);
        }
    }

    void SocketQuit()
    {
        //关闭线程
        if (connectThread != null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最后关闭服务器
        if (serverSocket != null)
            serverSocket.Close();
        print("diconnect");
    }

    // Use this for initialization
    void Start()
    {
        MsgMgr.Instance.Init();

        MsgMgr.Instance.SetMessageHandler<ServerLogin>(LoginHandler);
        MsgMgr.Instance.SetMessageHandler<ServerFullRows>(FullRowsHandler);

        InitSocket();

        DontDestroyOnLoad(gameObject);
    }

    // Update is called once per frame
    void Update()
    {
        List<NetPacket> netPackets = GetRecvBufferList();
        for (int i = 0; i < netPackets.Count; ++i)
        {
            NetPacket netPacket = netPackets[i];

            Type type = MsgMgr.Instance.GetType(netPacket.id);

            MsgMgr.MessageHandler handler = MsgMgr.Instance.GetMessageHandler(type);

            handler(netPacket.msg);
        }
    }

    private void OnDestroy()
    {
        Debug.Log("OnDestroy");
    }

    //程序退出则关闭连接
    void OnApplicationQuit()
    {
        SocketQuit();
    }

    public void AddRecvBuffer(byte[] recvBuffer)
    {
        lock (locker)
        {
            recvQueue.Add(recvBuffer);
        }
    }
    public List<NetPacket> GetRecvBufferList()
    {
        List<byte[]> bufferList = null;
        lock (locker)
        {
            bufferList = recvQueue;
            recvQueue = new List<byte[]>();
        }

        List<NetPacket> netPackets = new List<NetPacket>();

        for (int i = 0; i < bufferList.Count; ++i)
        {
            NetPacket netPacket = MsgMgr.Instance.GetNetPacket(bufferList[i]);
            netPackets.Add(netPacket);
        }

        return netPackets;
    }

    void LoginHandler(byte[] data)
    {
        ServerLogin serverLogin = new ServerLogin();
        serverLogin.MergeFrom(data);

        Debug.Log("Login success. username:" + serverLogin.Username + ", userid:" + serverLogin.Id);

        PlayerMgr.Instance.playerSelf = new Player
        {
            id = serverLogin.Id,
            username = serverLogin.Username,
            password = serverLogin.Password,
        };

        SceneManager.LoadScene("TetrisGame");


    }
    void FullRowsHandler(byte[] data)
    {
        ServerFullRows serverFullRows = new ServerFullRows();
        serverFullRows.MergeFrom(data);


        if (serverFullRows.Id == PlayerMgr.Instance.playerSelf.id)
        {
            return;
        }

        List<List<int>> rowsX = new List<List<int>>();

        for (int i = 0; i < serverFullRows.Row.Count; ++i)
        {
            Row row = serverFullRows.Row[i];
            List<int> x = new List<int>();
            for (int j = 0; j < row.X.Count; ++j)
            {
                x.Add(row.X[j]);
            }
            rowsX.Add(x);
        }

        Grid.AddFullRows(rowsX);

    }
}
